#pragma once
#include <algorithm>
#include <list>
#include <string>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "InetAddr.hpp"
#include "Log.hpp"
#include "mutex.hpp"

using namespace LogMudule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, std::string message) = 0;
    virtual bool operator==(const InetAddr &user) = 0;
};

class User : public UserInterface
{
public:
    User(const InetAddr &user) : _user(user)
    {
    }
    void SendTo(int sockfd, std::string message) override
    {
        LOG(LogLevel::INFO) << "send message to " << _user.Addr() << "Info is :" << message;
        ::sendto(sockfd, message.c_str(), message.size(), 0, _user.NetAddr(), _user.Len());
    }
    bool operator==(const InetAddr &user) override
    {
        return _user == user;
    }
    ~User() override
    {
    }

private:
    InetAddr _user;
};

// 观察者模式编写用户管理
class UserManage
{
public:
    UserManage() {}
    // 添加在线用户
    void AddUser(InetAddr &user)
    {
        // 多线程访问需要加锁
        _mutex.Lock();
        for (auto &u : _online_user)
        {
            if (*u == user)
            {
                LOG(LogLevel::INFO) << user.Addr() << " 用户已存在";
                //不释放会导致死锁
                _mutex.Unlock();
                return;
            }
        }
        _online_user.push_back(std::make_shared<User>(user));
        LOG(LogLevel::INFO) << "添加新用户"<<user.Addr();
        _mutex.Unlock();
    }
    // 轮询发送信息
    void Router(int sockfd, std::string message)
    {
        _mutex.Lock();
        for (auto &u : _online_user)
        {
            u->SendTo(sockfd, message);
        }
        _mutex.Unlock();
    }
    // 删除用户
    void DeleteUser(InetAddr &user)
    {        
        // 不会删除只会将目标元素移动到末尾
        auto pos = std::remove_if(_online_user.begin(), _online_user.end(), [&user](std::shared_ptr<UserInterface>& u) -> bool
                                  { return *u == user; });
        _online_user.erase(pos,_online_user.end());
    }
    ~UserManage() {}

private:
    std::list<std::shared_ptr<UserInterface>> _online_user;
    MutexModel::Mutex _mutex;
};